package com.springboot.middleware.middleware_lock.server.service;

import com.springboot.middleware.middleware_lock.model.entity.UserAccount;
import com.springboot.middleware.middleware_lock.model.entity.UserAccountRecord;
import com.springboot.middleware.middleware_lock.model.mapper.UserAccountMapper;
import com.springboot.middleware.middleware_lock.model.mapper.UserAccountRecordMapper;
import com.springboot.middleware.middleware_lock.server.dto.UserAccountDto;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;

@Service
public class DataBaseLockServiceImpl implements DataBaseLockService{
    private static final Logger log = LoggerFactory.getLogger(DataBaseLockServiceImpl.class);

    @Autowired
    private UserAccountMapper userAccountMapper;
    @Autowired
    private UserAccountRecordMapper userAccountRecordMapper;

    /**
     * 用户账户提取金额处理
     *
     * @param dto UserAccountDto
     * @throws Exception 账户不存在或账户余额不足
     */
    @Override
    public void takeMoney(UserAccountDto dto) throws Exception {
        //查询用户账户实体记录
        UserAccount userAccount = userAccountMapper.selectByUserId(dto.getUserId());
        //判断实体记录是否存在,以及账余额是否足够被提现
        if (userAccount != null && userAccount.getAmount().doubleValue() - dto.getAmount() >= 0) {
            //如果足够被提现,更新现有的账户余额(这里即为提现)
            userAccountMapper.updateAmount(userAccount.getId(), dto.getAmount());
            //同时记录提现成功时的记录
            UserAccountRecord record = new UserAccountRecord();
            record.setCreateTime(new Date());
            record.setAccountId(userAccount.getId());
            record.setMoney(BigDecimal.valueOf(dto.getAmount()));
            //插入申请提现金额历史
            userAccountRecordMapper.insert(record);
            log.info("当前提现的金额为{} 用户账户余额为{}",dto.getAmount(), userAccount.getAmount());
        } else {
            throw new Exception("账户不存在或账户余额不足");
        }
    }

    /**
     * 用户账户提取金额处理
     *
     * @param dto UserAccountDto
     * @throws Exception 账户不存在或账户余额不足
     */
    @Override
    public void takeMoneyWithLock(UserAccountDto dto) throws Exception {
        //查询用户账户实体记录
        UserAccount userAccount = userAccountMapper.selectByUserId(dto.getUserId());
        //判断实体记录是否存在,以及账余额是否足够被提现
        if (userAccount != null && userAccount.getAmount().doubleValue() - dto.getAmount() >= 0) {
            //如果足够被提现,更新现有的账户余额(这里即为提现)-采用version版本号机制
            int res = userAccountMapper.updateByPKVersion(userAccount.getId(), dto.getAmount(), userAccount.getVersion());
            if (res > 0) {
                //同时记录提现成功时的记录
                UserAccountRecord record = new UserAccountRecord();
                record.setCreateTime(new Date());
                record.setAccountId(userAccount.getId());
                record.setMoney(BigDecimal.valueOf(dto.getAmount()));
                //插入申请提现金额历史
                userAccountRecordMapper.insert(record);
                log.info("当前提现的金额为{} 用户账户余额为{}",dto.getAmount(), userAccount.getAmount());
            }
        } else {
            throw new Exception("账户不存在或账户余额不足");
        }
    }

    /**
     * 用户账户提取金额处理-悲观锁
     *
     * @param dto UserAccountDto
     * @throws Exception 账户不存在或账户余额不足
     */
    @Override
    public void takeMoneyWithNegativeLock(UserAccountDto dto) throws Exception {
        UserAccount userAccount = userAccountMapper.selectByUserIdLock(dto.getUserId());
        //判断实体记录是否存在,以及账余额是否足够被提现
        if (userAccount != null && userAccount.getAmount().doubleValue() - dto.getAmount() > 0) {
            int res = userAccountMapper.updateAmountLock(userAccount.getId(), dto.getAmount());
            if (res > 0) {
                UserAccountRecord record = new UserAccountRecord();
                record.setCreateTime(new Date());
                record.setAccountId(userAccount.getId());
                record.setMoney(BigDecimal.valueOf(dto.getAmount()));
                userAccountRecordMapper.insert(record);
                log.info("悲观锁处理方式-当前待提现的金额为: {} 用户账户金额为: {}", dto.getAmount(), userAccount.getAmount());
            } else {
                throw new Exception("悲观锁处理方式-账户不存在或账户余额不足!");
            }
        }
    }
}
